//  IDVI 1.0 source copyright 1996 Garth A. Dickie
//
//  This source is free for non-commercial use.  No warranty, etc.
//  Please acknowledge reuse by including the line:
//
//  "Based in part on IDVI 1.0 source copyright 1996 Garth A. Dickie"
//
//  in your documentation and source code.  For commercial use or
//  distribution, please contact the author.  Please also send
//  questions, comments, bug reports, or fixes.
//
//  Best Regards,
//  Garth A. Dickie
//  dickie@elastic.avid.com

package ibook.v10.idvi.io;

import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;

public final class DVIInputStream {
    public InputStream source;

    public DVIInputStream( InputStream source ) throws IOException {
        this.source = source;
    }

    public final void close( ) throws IOException {
        source.close( );
    }

    public final int read( ) throws IOException {
        return unsigned1( );
    }

    public final void read( byte[ ] dest ) throws IOException {
        read( dest, 0, dest.length );
    }

    public final void read( byte[ ] dest, int offset, int length ) throws IOException {
        int targetOffset = offset + length;

        do {
            int count = source.read( dest, offset, targetOffset - offset );
            if( count == -1 ) throw new EOFException( );
            offset += count;
        } while( offset != targetOffset );
    }

    public final String string( int length ) throws IOException {
        byte[ ] buffer = new byte[ length ];
        read( buffer );
        return new String( buffer, 0, 0, length );
    }

    public final void skip( long count ) throws IOException {
        long skipped;

        do {
            skipped = source.skip( count );
            count -= skipped;
        } while( count != 0 && skipped != 0 );

        if( count != 0 ) throw new EOFException( );
    }

    public final int signed( int count ) throws IOException {
        int result = ( int ) ( byte ) unsigned1( );

        while( -- count != 0 )
            result = ( result << 8 ) | unsigned1( );

        return result;
    }

    public final int signed1( ) throws IOException {
        return ( int ) ( byte ) unsigned1( );
    }

    public final int signed2( ) throws IOException {
        return signed( 2 );
    }

    public final int signed3( ) throws IOException {
        return signed( 3 );
    }

    public final int signed4( ) throws IOException {
        return signed( 4 );
    }

    public final int unsigned( int count ) throws IOException {
        int result = unsigned1( );

        while( -- count != 0 )
            result = ( result << 8 ) | unsigned1( );
        
        return result;
    }

    public final int unsigned1( ) throws IOException {
        int result = source.read( );

        if( result == -1 ) throw new EOFException( );

        return result;
    }

    public final int unsigned2( ) throws IOException {
        return unsigned( 2 );
    }

    public final int unsigned3( ) throws IOException {
        return unsigned( 3 );
    }

    public final int unsigned4( ) throws IOException {
        return unsigned( 4 );
    }

//  private int nybbleCache;
//  private int nybblesCached = 0;
//
//  public final int nybble( ) throws IOException {
//      if( nybblesCached == 0 ) {
//          nybbleCache = unsigned1( );
//          nybblesCached = 2;
//      }
//      return ( nybbleCache >> 4 * -- nybblesCached ) & 0xF;
//  }
//
//  public final void nybbleFlush( ) {
//      nybblesCached = 0;
//  }
//
//  private int bitCache;
//  private int bitsCached = 0;
//
//  public final int bit( ) throws IOException {
//      if( bitsCached == 0 ) {
//          bitCache = unsigned1( );
//          bitsCached = 8;
//      }
//      return ( bitCache >> -- bitsCached ) & 1;
//  }
//
//  public final void bitFlush( ) {
//      bitsCached = 0;
//  }
}
